JavaScript Proxyãã³ãã©ã®æé©åããã¹ã¿ãŒããåªããã€ã³ã¿ãŒã»ãã·ã§ã³ããã©ãŒãã³ã¹ãå®çŸãã°ããŒãã«ãªãŠãŒã¶ãŒã«åããã¢ããªã±ãŒã·ã§ã³ã®å¹çæ§ãšå¿çæ§ãè§£æŸããŸãã
JavaScript Proxyãã³ãã©ã®æé©åïŒã€ã³ã¿ãŒã»ãã·ã§ã³ããã©ãŒãã³ã¹ã®åäž
çŸä»£ã®JavaScriptéçºã®é åã«ãããŠãProxyãªããžã§ã¯ãã¯ãã¿ãŒã²ãããªããžã§ã¯ãã«å¯Ÿããåºæ¬çãªæäœãã€ã³ã¿ãŒã»ããïŒææïŒããããã®åŒ·åãªããŒã«ãšããŠååšããŸãããã®æè»æ§ã¯çãããããªããããªããŒã·ã§ã³ããã®ã³ã°ãã¢ã¯ã»ã¹å¶åŸ¡ãšãã£ãã¡ã¿ããã°ã©ãã³ã°èœåãå¯èœã«ããŸãããè€éãªãããã·ãã³ãã©ãããã©ãŒãã³ã¹ã«äžãã圱é¿ã¯èŠéããããã¡ã§ããå¿çæ§ãšå¹çæ§ãæéèŠèŠãããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã®ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããéçºè ã«ãšã£ãŠããããã·ãã³ãã©ã®ããã©ãŒãã³ã¹ãæé©åããããšã¯ãåãªãè¯ãç¿æ £ã§ã¯ãªããæ¥µããŠéèŠãªèŠä»¶ã§ãã
ãã®å æ¬çãªã¬ã€ãã§ã¯ãJavaScript Proxyãã³ãã©ã®æé©åã®è€éããæ·±ãæãäžããProxyãæäŸãããã¯ãŒãšè¡šçŸåãç ç²ã«ããããšãªããã€ã³ã¿ãŒã»ãã·ã§ã³ããã©ãŒãã³ã¹ãåäžãããããã®å®è·µçãªæŽå¯ãšé«åºŠãªãã¯ããã¯ãæäŸããŸããäžè¬çãªããã©ãŒãã³ã¹ã®ããã«ããã¯ãæŠç¥çãªãã³ãã©èšèšããããŠå¹ççã§ã¹ã±ãŒã©ãã«ãªãããã·å®è£ ãäœæããããã®ãã¹ããã©ã¯ãã£ã¹ãæ¢æ±ãããŠãŒã¶ãŒã®å Žæãããã€ã¹ã®èœåã«é¢ããããã¢ããªã±ãŒã·ã§ã³ãé«ãããã©ãŒãã³ã¹ãç¶æã§ããããã«ããŸãã
JavaScript Proxyãšãã³ãã©ã®çè§£
æé©åã«å ¥ãåã«ãJavaScript Proxyã®åºæ¬æŠå¿µãææ¡ããããšãéèŠã§ããProxyãªããžã§ã¯ãã¯ãtargetïŒã¿ãŒã²ããïŒãªããžã§ã¯ããšhandlerïŒãã³ãã©ïŒãªããžã§ã¯ãã®2ã€ã®åŒæ°ã§äœæãããŸãããã³ãã©ã¯ãã¿ãŒã²ããã«å¯ŸããŠå®è¡ãããæäœã®ã«ã¹ã¿ã ããã€ãã¢ãå®çŸ©ããŸãããããã®æäœã¯trapïŒãã©ããïŒãšããŠç¥ããã以äžã®ãããªãã®ãå«ãŸããŸãïŒ
- get(target, property, receiver): ããããã£ãžã®ã¢ã¯ã»ã¹ãã€ã³ã¿ãŒã»ããããŸãã
- set(target, property, value, receiver): ããããã£ãžã®ä»£å ¥ãã€ã³ã¿ãŒã»ããããŸãã
- has(target, property): `in`æŒç®åãã€ã³ã¿ãŒã»ããããŸãã
- deleteProperty(target, property): `delete`æŒç®åãã€ã³ã¿ãŒã»ããããŸãã
- apply(target, thisArg, argumentsList): 颿°åŒã³åºããã€ã³ã¿ãŒã»ããããŸãã
- construct(target, argumentsList, newTarget): `new`æŒç®åãã€ã³ã¿ãŒã»ããããŸãã
- ãã®ä»ãèªèº«ã®ããŒãããããã£ãã£ã¹ã¯ãªãã¿ããããã¿ã€ããžã®ã¢ã¯ã»ã¹ã®ããã®ãã©ãããªã©ã倿°ãããŸãã
åãã©ãã颿°ã¯ãåŒã³åºããããšãã¿ãŒã²ãããªããžã§ã¯ããåé¡ã®ããããã£ãããã³å Žåã«ãã£ãŠã¯ä»ã®åŒæ°ãåãåããŸãããã©ããå ã§ãéçºè ã¯ã¿ãŒã²ããã«å¯Ÿããããã©ã«ãã®æäœïŒå€ãã®å Žå`Reflect`ã¡ãœããã䜿çšïŒãå®è¡ããååŸã«ã«ã¹ã¿ã ããžãã¯ãå®è£ ãããããããå®å šã«ãªãŒããŒã©ã€ããããããããšãã§ããŸãã
ã€ã³ã¿ãŒã»ãã·ã§ã³ã®ããã©ãŒãã³ã¹ã³ã¹ã
Proxyã¯çµ¶å€§ãªãã¯ãŒãæäŸããŸãããã€ã³ã¿ãŒã»ããããããã¹ãŠã®æäœã«ã¯ãªãŒããŒããããçºçããŸãããã®ãªãŒããŒãããã¯ä»¥äžã®èŠå ããçããŸãïŒ
- 颿°åŒã³åºãã®ãªãŒããŒããã: åãã©ããã¯JavaScriptã®é¢æ°åŒã³åºãã§ãããããèªäœã«åºæã®ã³ã¹ããããããŸãã
- ããžãã¯å®è¡ã®ãªãŒããŒããã: ãã©ããå ã®ã«ã¹ã¿ã ããžãã¯ãå®è¡ããå¿ èŠããããŸããè€éãŸãã¯éå¹çãªããžãã¯ã¯ããã©ãŒãã³ã¹ã«å€§ããªåœ±é¿ãäžããŸãã
- `Reflect`åŒã³åºãã®ãªãŒããŒããã: ãã©ããã`Reflect`ã䜿çšããŠã¿ãŒã²ããã«åŠçãå§è²ããå Žåãããã«ããããã«é¢æ°åŒã³åºããšæäœã远å ãããŸãã
- ã¡ã¢ãªå²ãåœãŠ: Proxyãªããžã§ã¯ããšããã«é¢é£ãããã³ãã©ãäœæã»ç®¡çããããšã¯ã¡ã¢ãªãæ¶è²»ããå¯èœæ§ããããŸãã
åçŽãªã¢ããªã±ãŒã·ã§ã³ãé »åºŠã®äœãæäœã§ã¯ããã®ãªãŒããŒãããã¯ç¡èŠã§ãããããããŸããããããããªã¢ã«ã¿ã€ã ã®ããŒã¿æäœãè€éãªUIã®æŽæ°ããŸãã¯ãªããžã§ã¯ãã®ã€ã³ã¿ã©ã¯ã·ã§ã³ãå€ãã¢ããªã±ãŒã·ã§ã³ãªã©ãããã©ãŒãã³ã¹ãéèŠãªã·ããªãªã§ã¯ããã®çޝç©çãªãªãŒããŒããããé¡èãªé床äœäžãåŒãèµ·ãããç¹ã«ãããã¯ãŒã¯ã€ã³ãã©ãè匱ãªå°åãäœã¹ããã¯ã®ããã€ã¹ã§ã®ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããŸãã
Proxyãã³ãã©ã«ãããäžè¬çãªããã©ãŒãã³ã¹ã®ããã«ããã¯
ããã€ãã®äžè¬çãªãã¿ãŒã³ãå®è·µæ¹æ³ã¯ãæå³ããããŠProxyã䜿çšããéã®ããã©ãŒãã³ã¹äœäžã«ã€ãªããå¯èœæ§ããããŸãïŒ
1. éå°ãªã€ã³ã¿ãŒã»ãã·ã§ã³
ããã©ãŒãã³ã¹åé¡ã®æãçŽæ¥çãªåå ã¯ãå¿ èŠä»¥äžã«å€ãã®æäœãã€ã³ã¿ãŒã»ããããããšã§ãããŠãŒã¹ã±ãŒã¹ãããããã£ãžã®ã¢ã¯ã»ã¹ãšä»£å ¥ã®ã¿ãå¿ èŠãšããå Žåã`has`ã`deleteProperty`ã`apply`ãé¢é£ããªãã®ã§ããã°ããããã®ãã©ãããå®çŸ©ããå¿ èŠã¯ãããŸããã
äŸïŒèªã¿åãå°çšã¢ã¯ã»ã¹ã®ã¿ãç®çãšããŠèšèšãããProxyã¯ã倿Žãããããšãæå³ãããŠããªãå Žåã`set`ãã©ãããå®çŸ©ãã¹ãã§ã¯ãããŸããã空ã®`set`ãã©ãããå®çŸ©ããã ãã§ãã颿°åŒã³åºãã®ãªãŒããŒããããçºçããŸãã
2. éå¹çãªãã©ããããžãã¯
ãã©ããå ã®ããžãã¯ã¯ãããã©ãŒãã³ã¹ã®å€§ããªè¶³ãããšãªãåŸãŸããäžè¬çãªåå ã«ã¯ä»¥äžã®ãããªãã®ããããŸãïŒ
- é«ã³ã¹ããªèšç®: é »ç¹ã«åŒã³åºããããã©ããïŒäŸïŒãã¹ãŠã®ããããã£ã¢ã¯ã»ã¹ã«å¯Ÿãã`get`ïŒå ã§ãéãèšç®ãDOMæäœããŸãã¯è€éãªããŒã¿å€æãå®è¡ããããšã
- æ·±ãååž°ãŸãã¯å埩: å€§èŠæš¡ãªããŒã¿ã»ãããæäœãããã©ããå ã§ã®ã«ãŒããååž°åŒã³åºãã
- éå°ãªãªããžã§ã¯ãçæ: ãã©ããå ã§äžå¿ èŠã«æ°ãããªããžã§ã¯ããããŒã¿æ§é ãçæããããšã
- åææäœ: ãã©ããå ã§æéã®ãããåææäœã«ãã£ãŠã¡ã€ã³ã¹ã¬ããããããã¯ããããšã
3. äžèŠãª`Reflect`åŒã³åºã
`Reflect`ã¯æäœãã¿ãŒã²ãããªããžã§ã¯ãã«å§è²ããæšå¥šãããæ¹æ³ã§ãããã¿ãŒã²ããã«ååšããªãããŸãã¯æå³ããããããã·ã®åäœã®äžéšã§ã¯ãªãæäœã«å¯ŸããŠ`Reflect`ãåŒã³åºããšãå©çãªããªãŒããŒãããã远å ãããå¯èœæ§ããããŸãã
4. æé©åãããŠããªãããŒã¿æ§é
ã¿ãŒã²ãããªããžã§ã¯ãèªäœãéå¹çãªããŒã¿æ§é ïŒäŸïŒ`get`ãã©ããå ã§ç·åœ¢æ¢çŽ¢ããã倧ããªé åïŒã§ããå ŽåãProxyã®ããã©ãŒãã³ã¹ã¯æ¬è³ªçã«å¶éãããŸãã
5. Proxyã®é »ç¹ãªåäœæ
å°ããªå€æŽããšããŸãã¯äžæçãªãªããžã§ã¯ãã®ããã«æ°ããProxyã€ã³ã¹ã¿ã³ã¹ãäœæããããšã¯ãç¹ã«ã«ãŒãå ã§è¡ãããå Žåã倧ããªãªãŒããŒãããã«ã€ãªããå¯èœæ§ããããŸãã
Proxyãã³ãã©ã®ããã©ãŒãã³ã¹æé©åæŠç¥
ãããã·ãã³ãã©ã®ããã©ãŒãã³ã¹ãæé©åããã«ã¯ãèšèšãšå®è£ ã«å¯Ÿããæèçãªã¢ãããŒããå¿ èŠã§ãã以äžã«ããã€ãã®æŠç¥ã瀺ããŸãïŒ
1. æå°éã®ãã©ããå®çŸ©
å®è·µçãªæŽå¯ïŒã¢ããªã±ãŒã·ã§ã³ãæ¬åœã«ã€ã³ã¿ãŒã»ããããå¿ èŠã®ããæäœã«å¯ŸããŠã®ã¿ãã©ãããå®çŸ©ããŠãã ãããæäœãã¿ãŒã²ãããšå šãåãããã«åäœãã¹ãå Žåã¯ããã®ããã®ãã©ãããå®çŸ©ããªãã§ãã ãããããããã°ãJavaScriptãšã³ãžã³ã¯ããã©ã«ãã®åäœã䜿çšããŸãã
äŸïŒããããã£ã®èªã¿åããšæžã蟌ã¿ã®ã¿ããã°ã«èšé²ããå¿ èŠãããåçŽãªãã®ã³ã°ãããã·ã®å ŽåïŒ
const target = {
name: 'Example',
value: 10
};
const handler = {
get(target, prop, receiver) {
console.log(`Getting property "${String(prop)}"`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
console.log(`Setting property "${String(prop)}" to "${value}"`);
return Reflect.set(target, prop, value, receiver);
}
};
const proxiedObject = new Proxy(target, handler);
`has`ã`deleteProperty`ãªã©ã®ãã©ããã¯ããã®ç¹å®ã®ãã®ã³ã°æ©èœã«ã¯äžèŠãªããçç¥ãããŠããããšã«æ³šæããŠãã ããã
2. å¹ççãªãã©ããããžãã¯ã®å®è£
å®è·µçãªæŽå¯ïŒãã©ãã颿°å ã®ã³ãŒããã§ããã ã軜éãã€é«éã«ä¿ã¡ãŸããè€éãªèšç®ã¯ãå¥ã®æé©åããã颿°ãéåææäœã«ãªãããŒãããŸããé©åãªå Žåã«ã¯çµæããã£ãã·ã¥ããŸãã
äŸïŒ`get`ãã©ããå ã§è€éãªã«ãã¯ã¢ãããå®è¡ãã代ããã«ãããŒã¿ãäºååŠçããããããå¹ççãªããŒã¿æ§é ã䜿çšãããããŸãã
// Inefficient: Expensive lookup on every access
const handler = {
get(target, prop, receiver) {
if (prop === 'complexData') {
return performExpensiveLookup(target.id);
}
return Reflect.get(target, prop, receiver);
}
};
// Optimized: Pre-compute or use a cache
const cachedData = new Map();
const handlerOptimized = {
get(target, prop, receiver) {
if (prop === 'complexData') {
if (cachedData.has(target.id)) {
return cachedData.get(target.id);
}
const data = performExpensiveLookup(target.id);
cachedData.set(target.id, data);
return data;
}
return Reflect.get(target, prop, receiver);
}
};
3. `Reflect`ã®æŠç¥çãªäœ¿çš
å®è·µçãªæŽå¯ïŒ`Reflect`ã䜿çšããŠæäœãã¿ãŒã²ãããªããžã§ã¯ãã«å§è²ããŸãããåŒã³åºããã`Reflect`ã¡ãœãããå®éã«ãã®æäœã«é¢é£ããŠããããšã確èªããŠãã ããã`Reflect` APIã¯`Proxy`ãã©ããããã©ãŒãªã³ã°ããŠãããããã©ã«ãã®åäœãå®è¡ããããã®ã¯ãªãŒã³ãªæ¹æ³ãæäŸããŸãã
äŸïŒ`Reflect.get()`ã¡ãœããã¯ã`get`ãã©ããå ã§ã¿ãŒã²ããããããããã£ã®å€ãååŸããããã®æšæºçãªæ¹æ³ã§ããããã¯ã²ãã¿ãŒãåŠçãã`receiver`åŒæ°ãä»ããŠæ£ãã`this`ãã€ã³ãã£ã³ã°ãä¿èšŒããŸãã
const handler = {
get(target, prop, receiver) {
// Perform pre-get logic here if needed
const value = Reflect.get(target, prop, receiver);
// Perform post-get logic here if needed
return value;
}
};
4. ã¿ãŒã²ãããªããžã§ã¯ãã®æé©å
å®è·µçãªæŽå¯ïŒProxyã®ããã©ãŒãã³ã¹ã¯ãåºæ¬çã«ãã®ã¿ãŒã²ãããªããžã§ã¯ãã®ããã©ãŒãã³ã¹ã«ãã£ãŠå¶éãããŸããã¿ãŒã²ãããªããžã§ã¯ãèªäœããå®è¡ãããæäœã«å¯ŸããŠå¹ççãªããŒã¿æ§é ã§ããããšã確èªããŠãã ããã
äŸïŒãããã·ãé »ç¹ã«ããããã£ãæ€çŽ¢ããå Žåã`Map`ãæç¢ºã«å®çŸ©ãããããŒãæã€ãªããžã§ã¯ãã䜿çšããæ¹ããèŠçŽ ãèŠã€ããããã«ã«ã¹ã¿ã ã®`get`ããžãã¯ãå®è£ ããå¿ èŠããã倧ããªé åãããããã©ãŒãã³ã¹ãé«ããªãå¯èœæ§ããããŸãã
// Target: Array, inefficient for property lookup by ID
const usersArray = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
// Target: Map, efficient for property lookup by ID
const usersMap = new Map([
[1, { id: 1, name: 'Alice' }],
[2, { id: 2, name: 'Bob' }]
]);
// If your proxy frequently needs to find users by ID, using usersMap as the target is far more efficient.
5. ã¡ã¢åãšãã£ãã·ã³ã°
å®è·µçãªæŽå¯ïŒé »ç¹ã«å€æŽãããªãèšç®ãããŒã¿ååŸãè¡ããã©ããã«ã€ããŠã¯ããã³ãã©å ã«ã¡ã¢åãŸãã¯ãã£ãã·ã³ã°ãå®è£ ããŸããããã«ãããåé·ãªèšç®ãåé¿ã§ããŸãã
äŸïŒè€éãªããããã£èšç®ã®çµæããã£ãã·ã³ã°ããã
const handler = {
_cache: {},
get(target, prop, receiver) {
if (prop === 'calculatedValue') {
if (this._cache.calculatedValue !== undefined) {
return this._cache.calculatedValue;
}
const result = // ... perform complex calculation on target properties
this._cache.calculatedValue = result;
return result;
}
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
// If a property that affects 'calculatedValue' changes, clear the cache
if (prop !== 'calculatedValue') {
this._cache.calculatedValue = undefined;
}
return Reflect.set(target, prop, value, receiver);
}
};
6. ãããŠã³ã¹ãšã¹ããããªã³ã°ïŒã€ãã³ãã®ãããªãã©ããåãïŒ
å®è·µçãªæŽå¯ïŒãããã·ãã³ãã©ãé »ç¹ãã€æ¥éãªã€ãã³ãïŒäŸïŒUIã³ã³ããã¹ãå ïŒã«å¿çããå Žåããã©ããå ã®ã¢ã¯ã·ã§ã³ããããŠã³ã¹ãŸãã¯ã¹ããããªã³ã°ããŠãå®è¡ãããæäœã®æ°ãæžããããšãæ€èšããŠãã ããã
ããã¯çŽæ¥çãªProxyãã©ããã®æé©åã§ã¯ãããŸãããããã®ãã¯ããã¯ã¯ãã©ããã«ãã£ãŠ*ããªã¬ãŒããã*ã¢ã¯ã·ã§ã³ã«ããé©çšãããŸãã
7. ã«ãŒãå ã§ã®Proxyäœæã®åé¿
å®è·µçãªæŽå¯ïŒProxyãªããžã§ã¯ãã®äœæã¯ã³ã¹ãã®ãããæäœã§ããã«ãŒãå ã§ProxyãäœæããŠããããšã«æ°ã¥ããããããããªãã¡ã¯ã¿ãªã³ã°ã§ããªããæ€èšããŠãã ãããå€ãã®å Žåã1ã€ã®Proxyã§è€æ°ã®ã¿ãŒã²ãããªããžã§ã¯ããæäœã管çã§ããŸãã
äŸïŒãŠãŒã¶ãŒäœæã®ããªããŒã·ã§ã³ã®ã¿ãå¿ èŠãªå Žåã«ããªã¹ãå ã®åãŠãŒã¶ãŒãªããžã§ã¯ãã«å¯ŸããŠProxyãäœæãã代ããã«ïŒ
// Inefficient: Creating a proxy for each user object
const users = [];
for (const userData of rawUserData) {
const userProxy = new Proxy(userData, userValidationHandler);
users.push(userProxy);
}
// More efficient: A single handler for validation logic, applied when needed.
// Or a single proxy managing a collection.
8. Proxyã®éžæçãªäœ¿çš
å®è·µçãªæŽå¯ïŒã¢ããªã±ãŒã·ã§ã³å ã®ãã¹ãŠã®ãªããžã§ã¯ãããããã·åããå¿ èŠã¯ãããŸãããã¡ã¿ããã°ã©ãã³ã°æ©èœã倧ããªäŸ¡å€ãæäŸããããã©ãŒãã³ã¹ãžã®åœ±é¿ã蚱容ç¯å²å ã§ãããããŸãã¯è»œæžãããŠãããªããžã§ã¯ããã¢ãžã¥ãŒã«ã«æŠç¥çã«Proxyãé©çšããŠãã ããã
9. `Reflect.ownKeys`ãš`Object.getOwnPropertyNames`/`Symbols`ã®æŽ»çš
å®è·µçãªæŽå¯ïŒãªããžã§ã¯ãã®ããããã£ãå埩åŠçãããã©ããïŒ`ownKeys`ã`getOwnPropertyDescriptor`å ãªã©ïŒãå®è£ ããéã¯ãæãå¹ççãªã¡ãœããã䜿çšããŠããããšã確èªããŠãã ããã`Reflect.ownKeys`ã¯æååããŒãšã·ã³ãã«ããŒã®äž¡æ¹ãè¿ããããå€ãã®å Žåãæãå æ¬çã§ããã©ãŒãã³ã¹ã®é«ãéžæè¢ã§ãã
const handler = {
ownKeys(target) {
console.log('Getting own keys');
return Reflect.ownKeys(target);
}
};
10. ãã³ãããŒã¯ãšãããã¡ã€ãªã³ã°
å®è·µçãªæŽå¯ïŒæé©åã確å®ã«ããæã广çãªæ¹æ³ã¯æž¬å®ããããšã§ãããã©ãŠã¶ã®éçºè ããŒã«ïŒChrome DevToolsã®ããã©ãŒãã³ã¹ã¿ããªã©ïŒãNode.jsã®ãããã¡ã€ãªã³ã°ããŒã«ã䜿çšããŠãProxyå®è£ ã®ããã«ããã¯ãç¹å®ããŸããããŸããŸãªã¢ãããŒãããã³ãããŒã¯ããŠãç¹å®ã®ã³ã³ããã¹ãã§ã©ã¡ããæ¬åœã«é«éã§ãããã確èªããŠãã ããã
ã°ããŒãã«ã¢ããªã±ãŒã·ã§ã³ã«é¢ããèæ ®äºé ïŒãã³ãããŒã¯ãè¡ãéã¯ãçŸå®çãªãããã¯ãŒã¯ç¶æ³ãšããã€ã¹ã®ããã©ãŒãã³ã¹ãã·ãã¥ã¬ãŒãããŠãã ãããã€ã³ã¿ãŒãããé床ãé ãããŸãã¯æ§èœã®äœãããŒããŠã§ã¢ãæã€å°åã®ãŠãŒã¶ãŒãæš¡å£ããç°å¢ã§ã®ãã¹ããæ€èšããŠãã ãããLighthouseãWebPageTestã®ãããªããŒã«ã¯ãããŸããŸãªå Žæã§ã®å®éã®ããã©ãŒãã³ã¹ã«é¢ããæŽå¯ãæäŸã§ããŸãã
é«åºŠãªãŠãŒã¹ã±ãŒã¹ãšæé©åã·ããªãª
1. ããŒã¿ããªããŒã·ã§ã³ã®ããã®Proxy
Proxyã¯ããŒã¿ã®æŽåæ§ã匷å¶ããã®ã«åªããŠããŸããããªããŒã·ã§ã³ããžãã¯ã®æé©åãéµãšãªããŸãã
- ã¹ããŒãããŒã¹ã®ããªããŒã·ã§ã³: `set`ãã©ããå ã§è€éãª`if/else`ãã§ãŒã³ã䜿çšãã代ããã«ãäºåå®çŸ©ãããã¹ããŒããªããžã§ã¯ãã䜿çšããŸãããã©ããã¯ãã®ã¹ããŒããå¹ççã«ã¯ãšãªã§ããŸãã
- åãã§ãã¯ã®å¹çå: `typeof`ãè³¢ã䜿çšããŸããããè€éãªåãã§ãã¯ã«ã¯ãã©ã€ãã©ãªãäºåã³ã³ãã€ã«ãããããªããŒã·ã§ã³é¢æ°ã®äœ¿çšãæ€èšããŠãã ããã
- ããªããŒã·ã§ã³ã®ãããåŠç: å¯èœã§ããã°ãç¹ã«å€§èŠæš¡ãªããŒã¿æ§é ã«å¯ŸããŠãåã ã®ããããã£ä»£å ¥ããšã«ããªããŒã·ã§ã³ãè¡ãã®ã§ã¯ãªããããªããŒã·ã§ã³ããããåŠçããŸãã
åœéçãªäŸïŒã°ããŒãã«ãªeã³ããŒã¹ãã©ãããã©ãŒã ãæ³åããŠãã ããããŠãŒã¶ãŒã®äœæã¯ãåœåºæã®ãã©ãŒãããïŒéµäŸ¿çªå·ãéãã®ååãªã©ïŒã«åãããŠããªããŒã·ã§ã³ãå¿ èŠã§ããé©åã«æé©åããããããã·ã¯ããŠãŒã¶ãŒãæ¥æ¬ããã€ãããã©ãžã«ã®ã©ãã«ããŠãããã§ãã¯ã¢ãŠãããã»ã¹ãé ãããããšãªãããŒã¿ã®å質ãä¿èšŒã§ããŸãã
2. ãã®ã³ã°ãšç£æ»ã®ããã®Proxy
ãã¹ãŠã®æäœããã®ã³ã°ããããšã¯ãããã©ãŒãã³ã¹ã®ããã«ããã¯ã«ãªãå¯èœæ§ããããŸãã
- æ¡ä»¶ä»ããã®ã³ã°: ç¹å®ã®æ¡ä»¶ïŒäŸïŒç°å¢ããŠãŒã¶ãŒããŒã«ãç¹å®ã®ããããã£ïŒã«åºã¥ããŠã®ã¿æäœããã°ã«èšé²ããããžãã¯ãå®è£ ããŸãã
- éåæãã®ã³ã°: ãã®ã³ã°ã«æéããããå Žåã¯ãã¡ã€ã³ã¹ã¬ããããããã¯ããªãããã«éåæã§å®è¡ããŸãã
- ãµã³ããªã³ã°: ãã©ãã£ãã¯éã®å€ãã·ã¹ãã ã§ã¯ãæäœã®ãµã³ãã«ã®ã¿ããã°ã«èšé²ããŸãã
åœéçãªäŸïŒéèã¢ããªã±ãŒã·ã§ã³ã¯ãã¹ãŠã®ååŒãç£æ»ããå¿ èŠããããŸããæ©å¯ããŒã¿ãžã®ãã¹ãŠã®èªã¿åããŸãã¯æžã蟌ã¿ããã®ã³ã°ãããšãã·ã¹ãã ãéè² è·ã«ãªãå¯èœæ§ããããŸãããã®ã³ã°ãããã·ãæé©åããããšã§ãäžçäžã®ãŠãŒã¶ãŒã®ååŒãæ¯æããåŠçããã¢ããªã±ãŒã·ã§ã³ã®èœåã«åœ±é¿ãäžããããšãªããéèŠãªæäœããã°ã«èšé²ãããããšãä¿èšŒããŸãã
3. ã¢ã¯ã»ã¹å¶åŸ¡ãšæš©éã®ããã®Proxy
ãã¹ãŠã®ããããã£ã¢ã¯ã»ã¹ã§æš©éã確èªããã®ã¯ã³ã¹ãããããå¯èœæ§ããããŸãã
- æš©éã®ãã£ãã·ã³ã°: ç¹å®ã®ããããã£ããŠãŒã¶ãŒããŒã«ã«å¯Ÿããæš©éãã§ãã¯ããã£ãã·ã¥ããŸãã
- ããŒã«ããŒã¹ã®ãã§ãã¯: åããããã£ã®åå¥ã®æš©éã§ã¯ãªããäºåå®çŸ©ããããŠãŒã¶ãŒããŒã«ã«å¯ŸããŠå¹ççã«ãã§ãã¯ãããã³ãã©ãèšèšããŸãã
- ããã©ã«ãã§æåŠã®åå: æç€ºçã«èš±å¯ãããŠããªãéãæé»çã«ã¢ã¯ã»ã¹ãæåŠãããã©ãããå®è£ ããŸããããã«ãããããžãã¯ãåçŽã«ãªãããšããããŸãã
åœéçãªäŸïŒç°ãªããµãã¹ã¯ãªãã·ã§ã³å±€ãšãŠãŒã¶ãŒããŒã«ãæã€ã°ããŒãã«ãªSaaSãã©ãããã©ãŒã ããããã·ã¯æ©èœãããŒã¿ãžã®ã¢ã¯ã»ã¹ãå¹ççã«ç®¡çãããŠãŒã¶ãŒã倧éžãè¶ããŠããµãã¹ã¯ãªãã·ã§ã³ã§èš±å¯ãããŠãããã®ã ãã衚瀺ããæäœã§ããããã«ããŸãã
4. é å»¶èªã¿èŸŒã¿ãšä»®æ³åã®ããã®Proxy
Proxyã¯ãããŒã¿ãå®éã«å¿ èŠã«ãªããŸã§ããã®èªã¿èŸŒã¿ãèšç®ãé å»¶ãããããšãã§ããŸãã
- ãªã³ããã³ãã®ããŒã¿ååŸ: `get`ãã©ããã¯ãç¹å®ã®ããããã£ãåããŠã¢ã¯ã»ã¹ããããšãã«ã®ã¿APIåŒã³åºããããªã¬ãŒã§ããŸãã
- ä»®æ³ãããã·: 軜éãªãããã·ãªããžã§ã¯ããäœæããå¿ èŠãªå Žåã«ã®ã¿ãããéããå®å šã«ããŒãããããªããžã§ã¯ãã«åŠçãå§è²ããŸãã
åœéçãªäŸïŒã©ã³ãããŒã¯ã«é¢ãã詳现æ å ±ã衚瀺ããå°å³ã¢ããªã±ãŒã·ã§ã³ããããã·ã¯åã©ã³ãããŒã¯ã衚ãããšãã§ããŸãããŠãŒã¶ãŒãã©ã³ãããŒã¯ãã¯ãªãã¯ãããšããããã·ã®`get`ãã©ããããªã¢ãŒããµãŒããŒãã詳现æ å ±ïŒç»åã説æïŒãååŸããäžçäžã®ã©ãã«ãããŠãŒã¶ãŒã«å¯ŸããŠãåæã®å°å³èªã¿èŸŒã¿æéãæé©åããŸãã
ã°ããŒãã«ãªProxyãã³ãã©éçºã®ããã®ãã¹ããã©ã¯ãã£ã¹
ã°ããŒãã«ãªãªãŒãã£ãšã³ã¹åãã«JavaScript Proxyãéçºããéã«ã¯ã以äžã®ãã¹ããã©ã¯ãã£ã¹ãèæ ®ããŠãã ããïŒ
- Proxyã®äœ¿çšãåé¢ãã: Proxyã®å©ç¹ãæãé¡èãªç¹å®ã®ã¢ãžã¥ãŒã«ãããŒã¿æ§é ã«é©çšããŸããå¿ èŠã§ãªããã°ãã¢ããªã±ãŒã·ã§ã³ãªããžã§ã¯ãå šäœãProxyã«ããããšã¯é¿ããŠãã ããã
- é¢å¿ã®æç¢ºãªåé¢: ãããã·ãã³ãã©ã®ããžãã¯ãããã®ç¹å®ã®ã¡ã¿ããã°ã©ãã³ã°ã¿ã¹ã¯ïŒããªããŒã·ã§ã³ããã®ã³ã°ãªã©ïŒã«éäžãããé¢é£ã®ãªãæ©èœãæ··ããããšã¯é¿ããŠãã ããã
- 培åºçãªãã¹ã: Proxyããæ£ããã ãã§ãªããããŸããŸãªè² è·æ¡ä»¶äžã§ã®ããã©ãŒãã³ã¹ã«ã€ããŠãå³å¯ã«ãã¹ãããŸããã¯ãã¹ãã©ãŠã¶ããã³ã¯ãã¹ããã€ã¹ã®ãã¹ãã䜿çšããŠãã ããã
- ããã¥ã¡ã³ããŒã·ã§ã³: Proxyã®ç®çãšåäœãç¹ã«ãã®ããã©ãŒãã³ã¹ç¹æ§ãã¿ãŒã²ãããªããžã§ã¯ãã«é¢ããä»®å®ãæç¢ºã«ææžåããŠãã ããã
- ä»£æ¿æ¡ãæ€èšãã: ç¹å®ã®ã¿ã¹ã¯ã«ã¯ããã¬ãŒã³ãªJavaScriptãªããžã§ã¯ããã²ãã¿ãŒ/ã»ãã¿ãŒããŸãã¯å°çšã©ã€ãã©ãªã®æ¹ããProxyãããã·ã³ãã«ã§ããã©ãŒãã³ã¹ã®é«ããœãªã¥ãŒã·ã§ã³ãæäŸããããšããããŸããProxyãæ¬åœã«ãã®ä»äºã«æé©ãªããŒã«ã§ãããè©äŸ¡ããŠãã ããã
- ãšã©ãŒãã³ããªã³ã°: ãã©ããå ã«å ç¢ãªãšã©ãŒãã³ããªã³ã°ãå®è£ ããäºæãã¬ã¯ã©ãã·ã¥ãé²ãããŠãŒã¶ãŒã«æçãªãã£ãŒãããã¯ãæäŸããŸããç¹ã«ããšã©ãŒã¡ãã»ãŒãžã®æ éãªããŒã«ã©ã€ãºãå¿ èŠãªå€èšèªã³ã³ããã¹ãã§ã¯éèŠã§ãã
- å°æ¥ãžã®åã: ECMAScriptã®ä»æ§ããã©ãŠã¶/Node.jsãšã³ãžã³ã®ã¢ããããŒãã«åžžã«æ³šæãæããŸããããããã©ãŒãã³ã¹ç¹æ§ã¯é²åããå¯èœæ§ããããŸãã
çµè«
JavaScript Proxyã¯ãé«åºŠãªããã°ã©ãã³ã°ãã©ãã€ã ã«ãšã£ãŠäžå¯æ¬ ãªæ©èœã§ããã匷åãªã¡ã¿ããã°ã©ãã³ã°èœåãå¯èœã«ããŸããããããç¹ã«é«ãå¿çæ§ãèŠæ±ããã°ããŒãã«ãªã¢ããªã±ãŒã·ã§ã³ã«ãããããã©ãŒãã³ã¹ãžã®åœ±é¿ã¯ç¡èŠã§ããŸãããäžè¬çãªããã©ãŒãã³ã¹ã®ããã«ããã¯ãçè§£ããæå°éã®ãã©ããå®çŸ©ãå¹ççãªããžãã¯ãããã¹ããŒããªãã£ãã·ã³ã°ã`Reflect`ã®è³¢æãªäœ¿çšã«è³ããŸã§ãæé©åæŠç¥ãç±å¿ã«é©çšããããšã§ãéçºè ã¯Proxyã®å šãŠã®ãã¯ãŒã掻çšããªãããã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãšã¹ã±ãŒã©ããªãã£ã確ä¿ã§ããŸãã
æé©åã¯å埩çãªããã»ã¹ã§ããããšãå¿ããªãã§ãã ããããããã·å®è£ ãç¶ç¶çã«ãã³ãããŒã¯ãããããã¡ã€ãªã³ã°ããæ¹è¯ããŠãã ãããã°ããŒãã«ãªãªãŒãã£ãšã³ã¹ã«ãšã£ãŠããã®ããã©ãŒãã³ã¹ãžã®ã³ãããã¡ã³ãã¯ãããè¯ããããä¿¡é Œæ§ã®é«ããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ã«çŽæ¥ã€ãªããã倿§ãªåžå Žãæè¡çç°å¢å šäœã§ä¿¡é Œãšæºè¶³ãè²ã¿ãŸãããããã®ãã¯ããã¯ããã¹ã¿ãŒããããªãã®JavaScriptã¢ããªã±ãŒã·ã§ã³ã§æ°ããªã¬ãã«ã®å¹çæ§ãè§£ãæŸã¡ãŸãããã